package data;

import java.util.ArrayList;
import configs.Config;
import jmetal.core.Problem;
import jmetal.core.Solution;
import jmetal.core.SolutionSet;
import jmetal.util.JMException;

public class ProcessingData {

	private double INTERVALMAX = 0.9;
	private double INTERVALMIN = 0.1;
	
	private SetExample setTrain;
	private SetExample setCross;
	private SetExample setTest;

	private int numInputs;
	private int numOutputs;
	private SolutionSet solutions;
	protected Problem problem;

	private double min;
	private double max;

	public ProcessingData(SolutionSet solutions, Problem problem) throws JMException{
		Config.LOG.info("Start ProcessingData");
		
		this.numInputs = problem.getNumberOfObjectives();
		this.numOutputs = problem.getNumberOfVariables();
		this.solutions = solutions;
		this.problem = problem;
		this.setTrain = new SetExample();
		this.setCross = new SetExample();
		this.setTest = new SetExample();

		generate();
	}

	private void generate() throws JMException {
		Solution s;
		int size = solutions.size();
		double currentValue = 0;
		double[] inputs;
		double[] outputs;

		ArrayList<Example> examples = new ArrayList<Example>();
		Example ex;

		for (int i = 0; i < size; i++) {
			s = solutions.get(i);

			ex = new Example(s);
			inputs = ex.getInputs();
			outputs = ex.getOutputs();

			for (int z = 0; z < inputs.length; z++) {
				currentValue = inputs[z];

				if (currentValue > max)
					max = currentValue;
				if (currentValue < min)
					min = currentValue;
			}

			for (int z = 0; z < outputs.length; z++) {
				currentValue = outputs[z];

				if (currentValue > max)
					max = currentValue;
				if (currentValue < min)
					min = currentValue;
			}

			examples.add(ex);
		}

		// normalized data
		for (Example e : examples) {
			inputs = e.getInputs();
			outputs = e.getOutputs();

			for (int x = 0; x < inputs.length; x++) {
				inputs[x] = normalize(inputs[x]);
			}

			for (int x = 0; x < outputs.length; x++) {
				outputs[x] = normalize(outputs[x]);
			}

			e.setInputs(inputs);
			e.setOutputs(outputs);
		}

		if (size != 0) {

			int numTrain = size / 2;
			int numCross = size / 2;

			for(int t = 0 ; t < numTrain; t++)
			{
				int index = Config.random.nextInt(examples.size());
				setTrain.add(examples.remove(index));
			}
			
			for(int t = 0 ; t < numCross; t++)
			{
				int index = Config.random.nextInt(examples.size());
				setCross.add(examples.remove(index));
			}
			
			//setTest.addAll(examples);	
			
			Config.LOG.info("Processing Data - MaxValue = " + max + " MinValue = " + min);
		}

	}
	
	public int getNumInputs()
	{
		return numInputs;
	}
	
	public int getNumOutputs()
	{
		return numOutputs;
	}
	
	public SetExample getSetTrain()
	{
		return this.setTrain;
	}
	
	public SetExample getSetCross()
	{
		return this.setCross;
	}
	
	public SetExample getSetTest()
	{
		return this.setTest;
	}	

	private double normalize(double value) {
		double v = ((INTERVALMAX - INTERVALMIN)*(value - min)/(max - min)) + INTERVALMIN;
		//double v = value / max;
		if (v < INTERVALMIN || v > INTERVALMAX) {
			System.out.println("N: " + v);
		}
		return v;
	}
	
	public void normalize(double[] values)
	{
		for(int i = 0; i< values.length; i++)
		{
			values[i] = normalize(values[i]);
		}
	}

	public double originalValue(double value) {
		double v = ((value - INTERVALMIN)*(max - min))/(INTERVALMAX - INTERVALMIN) + min;
		//double v = value * max;
		if (v < 0) {
			//v = 0;
			System.out.println("value =" + value + " Original = " + v);
		}
		return v;
	}
	
	public void originalValue(double[] values)
	{
		for(int i = 0; i< values.length; i++)
		{
			values[i] = originalValue(values[i]);
		}
	}
}
